package xdu.lz.stage5_jucUtils.chapter5_lock.stampedlock;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.StampedLock;
import java.util.stream.Collectors;

/**
 * Created at 2019/10/20 0020 上午 10:14
 * <p>
 * R R 共享
 * R W 互斥
 * W W 互斥
 * W R 互斥
 * <p>
 * StampedLock实现ReentrantReadWriteLock的普通读写分离模式，采用StampedLock的悲观读
 *
 *
 * 悲观读：读的时候认为可能会被修改 ，所以不允许写操作
 * 假设有99个 read，1个write，那么会导致大部分时间都是在读，写的刷新频率很低。
 *
 */


/**
 * Demo1:利用StrampedLock实现ReentrantReadWriteLock
 */
public class StampedLock1 {

    private static StampedLock lock = new StampedLock();

    private static List<Long> data = new ArrayList<>();

    private static volatile long counter = 0;

    private static void read() {
        for (;;){
            long stamped = -1;
            try {
                //blocked api
                stamped = lock.readLock();

                //key是原数据，V是转换成字符串
                /*System.out.println(
                        data.stream().map(String::valueOf).
                                collect(Collectors.joining("#", "R-", "!")
                                ));*/
                System.out.println("read lock");
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlockRead(stamped);
            }
        }
    }

    private static void write() {
        for (;;){
            long stamped = -1;
            try {
                //blocked api
                stamped = lock.writeLock();
                data.add(++counter);
                System.out.println("write lock");
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlockWrite(stamped);
            }
        }

    }

    public static void main(String[] args) {
        ExecutorService service = Executors.newFixedThreadPool(100);

        Runnable readTask = StampedLock1::read;

        Runnable writeTask = StampedLock1::write;

        for (int i = 0; i < 99; i++) {
            service.submit(readTask);
        }
        service.submit(writeTask);

    }
}
